#include "Queue.h"
using namespace CSCI123;

Queue::Queue() : front(NULL), back(NULL) {
	/* empty */
}

Queue::Queue(const Queue& aQueue) {
	if (aQueue.front == NULL) {
		front = NULL;  // original list is empty
		back = NULL;
	} else {  
		// copy first node
		front = new QueueNode;
		front->data = aQueue.front->data;
		// copy rest of list
		QueueNodePtr newPtr = front;    // new list pointer
		QueueNodePtr origPtr = aQueue.front->next;

		for(;origPtr != NULL;origPtr = origPtr->next){  
			newPtr->next = new QueueNode;
			newPtr = newPtr->next;
			newPtr->data = origPtr->data;
		}
		newPtr->next = NULL;
		back = newPtr;
	}
}

Queue::~Queue() {
	while(!isEmpty()) {
		dequeue();
	}
	front = NULL;
	back = NULL;
}

void Queue::enqueue(const string& aString) {
	QueueNodePtr node = new QueueNode;
	node->data = aString;

	if(isEmpty()) {
		node->next = NULL;
		front = node;
		back = front;
	} else {
		node->next = NULL;
		back->next = node;
		back = node;
	}
}

string Queue::dequeue() {
	string data = "";
	if(!isEmpty()) {
		QueueNodePtr node = front;
		data = node->data;

		front = front->next;
		if(front == NULL)
			back = NULL;
		
		delete node;	
	}
	return data;
}

bool Queue::isEmpty() const {
	return (front == NULL);
}

ostream& CSCI123::operator <<(ostream& out, const Queue& aQueue) {
	if(aQueue.front == NULL)
		out << "Empty Queue!";
	for(QueueNodePtr cur = aQueue.front; cur != NULL; cur = cur->next) {
		if(cur == aQueue.front)
			out << "top->";
		else if(cur == aQueue.back)
			out << "back->";
		out << "\t" << cur->data << endl;
	}
	return out;
}
